package com.randy.fundation;


import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Locale;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class Logger {
    private static final String TAG = "Logger";

    public static void d(@NonNull String format, @Nullable Object... args) {
        String message = generate(String.format(format, args), false);
        Log.d(TAG, message);
    }

    public static void e(@NonNull String format, @Nullable Object... args) {
        String message = generate(String.format(format, args), false);
        Log.e(TAG, message);
    }

    public static void i(@NonNull String format, @Nullable Object... args) {
        String message = generate(String.format(format, args), false);
        Log.i(TAG, message);
    }

    public static void v(@NonNull String format, @Nullable Object... args) {
        String message = generate(String.format(format, args), false);
        Log.v(TAG, message);
    }

    public static void w(@NonNull String format, @Nullable Object... args) {
        String message = generate(String.format(format, args), false);
        Log.w(TAG, message);
    }


    private static String generate(@NonNull String message, boolean needAddTimeStamp) {
        StringBuilder builder = new StringBuilder();

        if (needAddTimeStamp) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd.hhmmss.S", Locale.US);
            String           date       = dateFormat.format(new java.util.Date());

            builder.append(date).append(" ");
        }

        Thread thread = Thread.currentThread();
        String name   = thread.getName();
        builder.append(name).append(" ");

        StackTraceElement[] traces = Thread.currentThread().getStackTrace();


        int stackIndex = getStackOffset(traces);

        StackTraceElement trace           = traces[stackIndex];
        String            fileName        = trace.getFileName();
        int               lineNumber      = trace.getLineNumber();
        String            className       = trace.getClassName();
        int               lastIndex       = className.lastIndexOf(".");
        String            simpleClassName = className.substring(lastIndex + 1);
        String            methodName      = trace.getMethodName();

        int    extIndex = fileName.lastIndexOf('.');
        String fileNameNoExt;
        if (extIndex != -1) {
            fileNameNoExt = fileName.substring(0, extIndex);
        } else {
            fileNameNoExt = fileName;
        }
        simpleClassName = simpleClassName.replace(fileNameNoExt, "");

        builder
                .append(fileName)
                .append(":")
                .append(lineNumber)
                .append(" ");
        if (simpleClassName.length() > 0) {
            builder.append(simpleClassName)
                   .append(".");
        }
        builder.append(methodName)
               .append("> ")
               .append(message);
        return builder.toString();
    }

    private static final int MIN_STACK_OFFSET = 3;

    static private int getStackOffset(@NonNull StackTraceElement[] traces) {
        String loggerClassName = Logger.class.getName();

        for (int i = MIN_STACK_OFFSET; i < traces.length; i++) {
            StackTraceElement trace = traces[i];
            String            name  = trace.getClassName();
            if (!name.equals(loggerClassName)) {
                return i;
            }
        }
        return -1;
    }
}
